package com.acmen.easyapi.executor;

import com.alibaba.fastjson.JSON;
import com.acmen.easyapi.model.Api;
import com.acmen.easyapi.model.App;
import com.acmen.easyapi.model.Environment;
import com.acmen.easyapi.model.MenuTree;
import com.acmen.easyapi.repository.ApiRepository;
import com.acmen.easyapi.repository.AppRepository;
import com.acmen.easyapi.repository.EnvironmentRepository;
import com.acmen.easyapi.util.ApiMenuTreeUtil;
import com.acmen.easyapi.util.FilesUtil;
import com.acmen.easyapi.util.Md5Util;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.ui.ModelMap;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 应用导出到HTML
 * @author acmen
 */
@Component
public class AppExportExe {
    @Autowired
    private AppRepository appRepository;
    @Resource
    private ApiRepository apiRepository;
    @Autowired
    private EnvironmentRepository environmentRepository;
    @Autowired
    private FreeMarkerConfigurer freeMarkerConfigurer;

    @Resource
    private ApiQueryExe apiQueryExe;
    private static final Logger log = LoggerFactory.getLogger(AppExportExe.class);

    /**
     * 导出到HTML
     * @param request
     * @param response
     * @throws IOException
     */
    public void exportHtml(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String appName = request.getParameter("appName");
        List<String> apiIds = Arrays.asList(request.getParameter("apiIds").split(","));
        App app = appRepository.selectByName(appName);
        List<Api> apis = apiRepository.selectListByIds(apiIds);
        app.setApis(apis);
        String prefix = Md5Util.md5(request.getParameter("apiIds"));
        ModelMap model = new ModelMap();
        model.put("app", app);
        List<Environment> environments = environmentRepository.getGatewayEnvironments(appName);
        model.put("environments", environments);

        MenuTree devGuide = new MenuTree("开发指南");
        devGuide.getChildrens().add(new MenuTree("● 接口公共说明","./html/note.html"));
        MenuTree menuTree = ApiMenuTreeUtil.getApiMenuTree(apis);
        menuTree.getChildrens().add(0,devGuide);
        model.put("menuTree", JSON.toJSONString(menuTree));
        String temFilePath = getTemFilePath();
        log.info("临时文件目录：{}", temFilePath);
        String exportPath = temFilePath + "/" + prefix + "/export/";
        try {
            model.put("contextPath", ".");
            //生成首页
            String htmlStr = generate("export/app.ftl", model);
            FilesUtil.saveFileByBytes(htmlStr.getBytes(StandardCharsets.UTF_8), exportPath, "index.html");
            model.put("contextPath", "../libary/");
            //生成公共说明页
            htmlStr = generate("app/note.ftl", model);
            FilesUtil.saveFileByBytes(htmlStr.getBytes(StandardCharsets.UTF_8), exportPath+"/html/", "note.html");
            //生成详情页
            for (Api a : apis) {
                ModelMap apiModel = new ModelMap();
                apiModel.addAllAttributes(model);
                apiModel.addAllAttributes(apiQueryExe.apiDetail(request,a.getId()));
                apiModel.put("contextPath", "..");
                htmlStr = generate("export/api.ftl", apiModel);
                FilesUtil.saveFileByBytes(htmlStr.getBytes(StandardCharsets.UTF_8), exportPath + "/html/", a.getId() + ".html");
            }
            FilesUtil.copySourceFile("classpath:static/jquery/*.*" , exportPath+"/libary/", Arrays.asList(".js"));
            FilesUtil.copySourceFile("classpath:static/vue/*.*" , exportPath+"/libary/", Arrays.asList(".js"));
            FilesUtil.copySourceFile("classpath:static/js/*.*" , exportPath+"/libary/", Arrays.asList(".js"));
            FilesUtil.copySourceFile("classpath:static/js/api/*.*" , exportPath+"/libary/", Arrays.asList(".js"));
            FilesUtil.copySourceFile("classpath:static/css/*.*" , exportPath+"/libary/", Arrays.asList(".css",".ttf",".woff"));
            FilesUtil.copySourceFile("classpath:static/css/fonts/*.*" , exportPath+"/libary/", Arrays.asList(".ttf",".woff"));
        } catch (TemplateException e) {
            e.printStackTrace();
        }
        String zipName = app.getNote() + "_接口文档_" + DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDateTime.now());
        FilesUtil.downloadZip(response, exportPath, zipName);
        new File(exportPath).delete();
    }

    /**
     * 导出到PDF
     * @param request
     * @param response
     */
    public void exportPdf(HttpServletRequest request, HttpServletResponse response){
        String appName = request.getParameter("appName");
        List<String> apiIds = Arrays.asList(request.getParameter("apiIds").split(","));
        App app = appRepository.selectByName(appName);
        List<Api> apis = apiRepository.selectListByIds(apiIds);
        app.setApis(apis);
        String prefix = Md5Util.md5(request.getParameter("apiIds"));
        ModelMap model = new ModelMap();
        model.put("app", app);
        List<Environment> environments = environmentRepository.getGatewayEnvironments(appName);
        model.put("environments", environments);
        MenuTree devGuide = new MenuTree("开发指南");
        devGuide.getChildrens().add(new MenuTree("● 接口公共说明","./html/note.html"));
        MenuTree menuTree = ApiMenuTreeUtil.getApiMenuTree(apis);
        menuTree.getChildrens().add(0,devGuide);
        model.put("menuTree", JSON.toJSONString(menuTree));
        try {
            model.put("contextPath", ".");
            ModelMap apiModel = new ModelMap();
            apiModel.addAllAttributes(model);
            apiModel.put("contextPath", "..");
            List<ModelMap> modelMaps = new ArrayList<>();
            request.setAttribute("exportPdf",true);
            for (Api a : apis) {
                ModelMap modelMap = apiQueryExe.apiDetail(request,a.getId());
                modelMap.put("api",a);
                modelMaps.add(modelMap);
            }
            apiModel.put("modelMaps",modelMaps);
            String html = generate("export/pdf-api.ftl", apiModel);
            String fileName = app.getNote() + "_接口文档_" + DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDateTime.now())+".pdf";
            FilesUtil.downloadPdf(response,html,fileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private String generate(String templatePath, Map<String, Object> variables) throws TemplateException, IOException {
        Template template = freeMarkerConfigurer.getConfiguration().getTemplate(templatePath);
        String htmlStr = FreeMarkerTemplateUtils.processTemplateIntoString(template, variables);
        return htmlStr;
    }


    /**
     * 获取临时文件路径
     *
     * @return
     */
    private String getTemFilePath() {
        return System.getProperty("java.io.tmpdir");
    }

}
